/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package demo.reflection;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;

/**
 *
 * @author VANDH
 */
public class Main {

    public static void examClass(Class c) {
        System.out.println("List of constructor ");
        System.out.println("---------------------------------------");

        // getConstructors() -> Constructor[]
        for (Constructor co : c.getConstructors()) {
            System.out.printf("%s%n", co.toGenericString());
        }
    }

    private static void examMethod(Class c) throws NoSuchMethodException {
        // Lấy object Method từ tên và kiểu tham số
        String methodName = "setCount";
        Method m = c.getMethod(methodName, int.class);

        // m -> setCount(int c)
        System.out.println(m.toGenericString());

        // Show thông tin method từ object Method đã có
        System.out.println("---------------------------");
        System.out.println(m.getName());
        Class[] paramters = m.getParameterTypes();

        for (Class i : paramters) {
            System.out.println(i.toString());
        }
    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        int choice;
        Scanner keyboard = new Scanner(System.in);

        do {
            System.out.println("1. Xem thông tin của một class");
            System.out.println("2. Xem thông tin của một hàm");
            System.out.println("3. Tạo object động, gọi hàm động");
            System.out.println("4. Tạo mảng động");
            System.out.println("5. Liệt kê tất cả field");
            System.out.println("6. Liệt kê tất cả method");
            System.out.println("0. Thoát");
            choice = keyboard.nextInt();

            switch (choice) {
                case 1:
                    String className = "demo.reflection.MyClass";
                    Class c = Class.forName(className);
                    examClass(c);
                    break;
                case 2:
                    className = "demo.reflection.MyClass";
                    c = Class.forName(className);
                    examMethod(c);
                    break;
                case 3:
                    createObject();
                    break;
                case 4:
                    createArray();
                    break;
                case 5:
                    c = MyClass.class; // -> Class
                    listFields(c);
                    break;
                case 6:
                    c = MyClass.class; // -> Class
                    listMethods(c);
                    break;
            }
        } while (choice != 0);
    }

    private static void listFields(Class c) throws SecurityException {
        System.out.println("List of fields ");
        System.out.println("---------------------------------------");

        for (Field f : c.getFields()) {
            System.out.printf("%s%n", f.toGenericString());
        }
    }

    private static void listMethods(Class c) throws SecurityException {
        System.out.println("List of methods ");
        System.out.println("---------------------------------------");

        for (Method m : c.getMethods()) {
            System.out.printf("%s%n", m.toGenericString());
        }
    }

    private static void createObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
        // Tạo object động
        String className = "demo.reflection.MyClass";
        Class c = Class.forName(className);

//         c là Class chứa thông tin class "demo.reflection.Class"
//         dùng c.newInstance() để tạo ra object bằng constructor mặc định

        Object s = c.newInstance(); // Object s = new MyClass();
        Method m = c.getMethod("getCount");
        Integer i = (Integer) m.invoke(s);
        System.out.println(i);

        Constructor co = c.getConstructor(int.class);
        s = co.newInstance(10);   // s = new MyClass(10);
        System.out.println(s);
    }

    private static void createArray() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        int count = 3;
        String className = "demo.reflection.MyClass";
        Class c = Class.forName(className);

        Object ar = Array.newInstance(c, count);


        Array.set(ar, 0, c.newInstance());
        Array.set(ar, 1, c.newInstance());
        Array.set(ar, 2, c.newInstance());

        for (int i = 0; i < Array.getLength(ar); i++) {
            System.out.println(Array.get(ar, i));
        }
    }
}
